package com.example.codereview.swing;

import com.intellij.util.ui.ImageUtil;
import lombok.Data;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.rtf.RTFEditorKit;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author xianfeng
 * @date 2024/11/11 11:55
 * @description:
 */
public class CustomJTextPane extends JTextPane {

    public CustomJTextPane() {
        super();
    }

    public JTextPaneContent serializeContent() {
        StyledDocument doc = this.getStyledDocument();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        RTFEditorKit rtfKit = new RTFEditorKit();
        try {
            rtfKit.write(baos, doc, 0, doc.getLength());
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (BadLocationException e) {
            throw new RuntimeException(e);
        }

        List<ImagePosition> images = new ArrayList<>();
        for (int i = 0; i < doc.getLength(); i++) {
            Element element = doc.getCharacterElement(i);
            AttributeSet as = element.getAttributes();

            Component comp = StyleConstants.getComponent(as);
            if (comp instanceof JLabel && ((JLabel) comp).getIcon() instanceof ImageIcon) {
                ImageIcon imageIcon = (ImageIcon) ((JLabel) comp).getIcon();
                ImagePosition imagePosition = new ImagePosition();
                imagePosition.setImageIcon(imageIcon);
                imagePosition.setPosition(i);
                images.add(imagePosition);
            }
        }
        JTextPaneContent textPaneContent = new JTextPaneContent();
        textPaneContent.setImages(images);
        textPaneContent.setRTFContent(baos.toByteArray());
        return textPaneContent;
    }

    public void deSerializeContent(JTextPaneContent content) {
        StyledDocument doc = (StyledDocument) new RTFEditorKit().createDefaultDocument();
        ByteArrayInputStream bais = new ByteArrayInputStream(content.getRTFContent());
        RTFEditorKit rtfKit = new RTFEditorKit();
        try {
            rtfKit.read(bais, doc, 0);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (BadLocationException e) {
            throw new RuntimeException(e);
        }
        List<ImagePosition> images = content.getImages();
        for (int i = 0; i < images.size(); i++) {
            SimpleAttributeSet attrSet = new SimpleAttributeSet();
            BufferedImage bufferedImage = convertImageIcon(images.get(i).getImageIcon());
            SmoothResizableImageLabel imageLabel = new SmoothResizableImageLabel(bufferedImage);
            StyleConstants.setComponent(attrSet, imageLabel);
            try {
                doc.insertString(images.get(i).getPosition(), " ", attrSet); // 插入图片
            } catch (BadLocationException e) {
                throw new RuntimeException(e);
            }
        }
        //去除结尾的"\n"
        try {
            String docText = doc.getText(0, doc.getLength());
            if (docText.endsWith("\n")) {
                try {
                    doc.remove(doc.getLength() - 2, 2); // 去除最后的换行符
                } catch (BadLocationException e) {
                    e.printStackTrace();
                }
            }
        } catch (BadLocationException e) {
            throw new RuntimeException(e);
        }
        this.setStyledDocument(doc);
    }


    public void pasteImage() {
        JTextPane textPane = this;
        Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
        if (t != null && t.isDataFlavorSupported(DataFlavor.imageFlavor)) {
            try {
                Image image = (Image) t.getTransferData(DataFlavor.imageFlavor);
                BufferedImage bufferedImage = ImageUtil.createImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
                Graphics2D g2d = bufferedImage.createGraphics();
                g2d.drawImage(image, 0, 0, null);
                g2d.dispose();
                // 创建可调整大小的图片组件并插入到 textPane
                SmoothResizableImageLabel imageLabel = new SmoothResizableImageLabel(bufferedImage);
                SimpleAttributeSet attrSet = new SimpleAttributeSet();
                StyleConstants.setComponent(attrSet, imageLabel);

                textPane.getStyledDocument().insertString(textPane.getCaretPosition(), " ", attrSet); // 插入占位符，代表图片位置
            } catch (UnsupportedFlavorException | IOException ex) {
                ex.printStackTrace();
            } catch (BadLocationException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static BufferedImage convertImageIcon(ImageIcon icon) {
        BufferedImage bufferedImage = new BufferedImage(
                icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = bufferedImage.createGraphics();
        g2d.drawImage(icon.getImage(), 0, 0, null);
        g2d.dispose();
        return bufferedImage;
    }


    static class SmoothResizableImageLabel extends JLabel implements Serializable {
        private int mouseX, mouseY;
        private final int CORNER_SIZE = 10; // 拖拽角的大小
        private final Cursor SE_RESIZE_CURSOR = new Cursor(Cursor.SE_RESIZE_CURSOR);
        private final Cursor DEFAULT_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR);

        private boolean isResizing = false;
        private transient BufferedImage originalImage;
        private Dimension targetSize; // 用于记录目标尺寸

        private byte[] imageData; // 存储序列化的字节流数据

        public SmoothResizableImageLabel(BufferedImage image) {
            super(new ImageIcon(image));
            this.imageData = serializeImage(image); // 将图像序列化为字节流
            this.originalImage = image;
            this.targetSize = new Dimension(image.getWidth(), image.getHeight());
            setSize(targetSize);
            setBorder(BorderFactory.createLineBorder(Color.GRAY, 1));

            addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    if (isInCorner(e.getX(), e.getY())) {
                        isResizing = true;
                        mouseX = e.getX();
                        mouseY = e.getY();
                        setCursor(SE_RESIZE_CURSOR);
                    }
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    isResizing = false;
                    setCursor(DEFAULT_CURSOR);
                    resizeImageToTargetSize(); // 在拖动结束时更新图片大小
                }
            });

            addMouseMotionListener(new MouseAdapter() {
                @Override
                public void mouseMoved(MouseEvent e) {
                    if (isInCorner(e.getX(), e.getY())) {
                        setCursor(SE_RESIZE_CURSOR);
                    } else {
                        setCursor(DEFAULT_CURSOR);
                    }
                }

                @Override
                public void mouseDragged(MouseEvent e) {
                    if (isResizing) {
                        int deltaX = e.getX() - mouseX;
                        int deltaY = e.getY() - mouseY;

                        int newWidth = Math.max(20, getWidth() + deltaX);
                        int newHeight = Math.max(20, getHeight() + deltaY);

                        targetSize.setSize(newWidth, newHeight);
                        setSize(targetSize);
                        revalidate();
                        repaint();
                    }
                }
            });
        }

        // 判断鼠标是否在图片的右下角区域
        private boolean isInCorner(int x, int y) {
            return x >= getWidth() - CORNER_SIZE && y >= getHeight() - CORNER_SIZE;
        }

        // 用高质量的模式缩放图片
        private void resizeImageToTargetSize() {
            BufferedImage resizedImage = new BufferedImage(
                    targetSize.width, targetSize.height, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = resizedImage.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.drawImage(originalImage, 0, 0, targetSize.width, targetSize.height, null);
            g2d.dispose();

            setIcon(new ImageIcon(resizedImage));
        }


        // 将图像转换为字节流
        private byte[] serializeImage(BufferedImage image) {
            try {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ImageIO.write(image, "png", baos); // 使用 PNG 格式
                baos.flush();
                return baos.toByteArray();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }

        // 反序列化图像
        private void deserializeImage() {
            if (imageData != null) {
                try {
                    ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
                    originalImage = ImageIO.read(bais);
                    setIcon(new ImageIcon(originalImage)); // 显示反序列化后的图像
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        // 重写 readObject 来处理反序列化
        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
            in.defaultReadObject(); // 默认反序列化
            deserializeImage(); // 反序列化图像
        }
    }

    @Data
    public static class JTextPaneContent implements Serializable {
        private byte[] rTFContent;
        private List<ImagePosition> images;
    }

    @Data
    public static class ImagePosition implements Serializable {
        private int position;
        private ImageIcon imageIcon;
    }
}
